#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
#include <string>
#include <map>
#include <array>
#include <cassert>
#include <string.h>
#include <list>
#include "list.h"
using namespace std;
namespace wh
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;
		iterator begin()
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}
		const_iterator begin() const
		{
			return _str;
		}
		const_iterator end() const
		{
			return _str + _size;
		}
		string(const char* str = "")
			:_size(strlen(str))
			, _capacity(_size)
		{
			cout << "string(char* st)" << endl;
			_str = new char[_capacity + 1];
			strcpy(_str, str);

		}
		string(size_t n, char ch = '\0')
		{
			cout << "string(size_t n, char ch = '\\0')" << endl;
			reserve(n);
			for (int i = 0; i < n; i++)
			{
				_str[i] = ch;
			}
			_str[n] = '\0';
			_size = n;
		}
		void swap(string& s)
		{
			::swap(_str, s._str);
			::swap(_size, s._size);
			::swap(_capacity, s._capacity);
		}
		//拷贝构造 - 左值
		string(const string& s)
			:_str(nullptr)
		{
			cout << "string(const string& s) -- 深拷贝" << endl;
			reserve(s._capacity);
			for (auto ch : s)
			{
				push_back(ch);
			}
		}
		//赋值重载
		string& operator=(const string& s)
		{
			cout << "string& operator=(string s) -- 深拷贝" << endl;
			if (this != &s)
			{
				_str[0] = '\0';
				_size = 0;
				reserve(s._capacity);
				for (auto ch : s)
				{
					push_back(ch);
				}
			}
			return *this;
		}
		//移动构造 - 右值
		//临时创建的对象,不能取地址,用完就要消亡了
		string(string&& s)
			:_str(nullptr)
			, _size(0)
			, _capacity(0)
		{
			cout << "string(string&& s) -- 移动拷贝" << endl;
			swap(s);//直接抢夺资源
		}
		//移动赋值
		string& operator=(string&& s)
		{
			cout << "operator=(string&& s) -- 移动拷贝" << endl;
			swap(s);
			return *this;
		}
		~string()
		{
			delete[] _str;
			_str = nullptr;
		}
		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return _str[pos];
		}
		void reserve(size_t n)
		{
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];
				if (_str)
				{
					strcpy(tmp, _str);
					delete[] _str;
				}
				_str = tmp;

				_capacity = n;
			}
		}
		void push_back(char ch)
		{
			if (_size >= _capacity)
			{
				size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
				reserve(newcapacity);
			}
			_str[_size] = ch;
			++_size;
			_str[_size] = '\0';
		}
		template <class... Args>
		/*void emplace_back(Args&&... args)
		{
			insert(end(), move(x));
		}*/
		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}
		const char* c_str() const
		{
			return _str;
		}
	private:
		char* _str = nullptr;
		size_t _size = 0;
		size_t _capacity = 0;
	};
}


//int main()
//{
//	hao::list<wh::string> lt;
//	wh::string s1("111111");
//	//emplace_back的特点是既能接收左值也可以接收右值
//	//直接传递的时候跟push_back是一样的
//	lt.emplace_back(s1);//左值
//	lt.emplace_back(move(s1));//右值
//	lt.emplace_back("111111111");
//	lt.emplace_back(10, 'x');
//	return 0;
//}


int main()
{
	hao::list<wh::string> lt;
	wh::string s1("111111");
	//emplace_back的特点是既能接收左值也可以接收右值
	//直接传递的时候跟push_back是一样的
	lt.emplace_back(s1);//左值
	lt.emplace_back(move(s1));//右值

	//emplace_back是可变参数模板,难道支持插入多个值?
	//lt.emplace_back(1, 2, 3);//其实是不支持的
	

	hao::list<pair<wh::string,int>> it1;
	//如果用push_back只能push_back一个对象,因为push_back的参数是固定的
	//构造pair + 拷贝/移动构造pair到list的节点中data上
	pair<wh::string, int> kv("苹果", 1);
	it1.emplace_back(kv);//左值
	it1.emplace_back(move(kv));//右值

	cout << endl << endl;
	//那这个可变参数模板到底是要干嘛呢? - 其实是针对多参数的
	//可以不传pair,直接把pair的参数当做可变参数往下传
	//直接把构造pair的参数包往下传,不着急构造,一直往下传,直到构造链表节点
	//的时候用这两个值构造节点即可。
	//直接把构造pair参数包往下传,直接用pair参数包构造pair
	it1.emplace_back("苹果", 1);//直接构造
	//直接把构造string参数包往下传,直接用string参数包构造string
	lt.emplace_back("111111111");
	lt.emplace_back(10, 'x');


	return 0;
}



//template <class T>
//void printArgs(T&& t)
//{
//	cout << t << " ";
//}
//
//void showList(int x, char ch, std::string s)
//{
//	//cout的返回值ostream类型的对象,不能初始化这个数组
//	//int arr[] = { cout << (x) << " ",cout << (ch) << " " ,cout << (s) << " " };
//	int arr[] = { (cout << (x) << " ",0),(cout << (ch) << " ",0) ,(cout << (s) << " ",0) };
//	cout << endl;
//}
//template <class ...Args>
//void showList(Args... args)
//{
//	//cout的返回值ostream类型的对象,不能初始化这个数组
//	//int arr[] = { (cout << (args) << " ",0)...};
//	//ostream类型的对象不支持拷贝
//	//ostream arr[] = { cout << (args) << " "...};
//	//数组不支持引用,auto也不行,auto是不支持数组的
//	ostream& arr[] = { cout << (args) << " "...};
//	cout << endl;
//}
//int main()
//{
//	showList(1, 'A', std::string("insert"));
//	return 0;
//}


//template <class T>
//void printArgs(T&& t)
//{
//	cout << t << " ";
//}
//template <class ...Args>
//void showList(Args&&... args)
//{
//	//这样写就说明把参数包依次展开,展开了就会有多个PrintArgs,
//	//参数包有几个,就有几个PrintArgs,然后数组就会开多大
//	//cout的返回值是ostream类型的对象,所以要加逗号表达式
//	//如果返回值用ostream的话也不行,ostream不支持拷贝
//	int arr[] = { (cout << (args) << " ",0)...};
//	cout << endl;
//}
//int main()
//{
//	showList(1, 'A', std::string("insert"));
//	return 0;
//}


//template <class T>
//int PrintArgs(T&& x)
//{
//	cout << x << " ";
//	return 0;
//}
////template <class ...Args>
////void showList(Args... args)
////{
////	int arr[] = { PrintArgs(args)... };
////	cout << endl;
////}
////编译推演生成下面的函数
//void showList(int x,char ch,std::string s)
//{
//	//这样写就说明把参数包依次展开,展开了就会有多个PrintArgs,
//	//参数包有几个,就有几个PrintArgs,然后数组就会开多大
//	int arr[] = { PrintArgs(x),PrintArgs(ch),PrintArgs(s) };
//	cout << endl;
//}
//int main()
//{
//	showList(1, 'A', std::string("insert"));
//	return 0;
//}


//template <class T>
//int PrintArgs(T&& x)
//{
//	cout << x << " ";
//	return 0;
//}
//template <class ...Args>
//void showList(Args... args)
//{
//	int arr[] = { PrintArgs(args)... };
//	cout << endl;
//
//}
//int main()
//{
//	showList(1);
//	showList(1,'A');
//	showList(1,'A', std::string("insert"));
//	return 0;
//}

//template <class T, class ...Args>
//void Print(T&& x, Args&&... args)
//{
//	cout << x << " ";
//	Print(args...);
//}
//void Print()
//{
//	cout << endl;
//}
//void Print(double z)
//{
//	cout << z << " ";
//	Print();
//}
//void Print(const char* y, double z)
//{
//	cout << y << " ";
//	Print(z);
//}
//void Print(int x, const char* y, double z)
//{
//	cout << x << " ";
//	Print(y,z);
//}
//template <class ...Args>
//void showList(Args&&... args)
//{
//	Print(args...);
//}
//底层
//void showList(int x,const char* y,double z)
//{
//	Print(x,y,z);
//}
//int main()
//{
//	showList(1, "x", 3.14);
//	return 0;
//}


//void Print()
//{
//	cout << endl;
//}
//template <class T,class ...Args>
//void Print(T&& x, Args&&... args)
//{
//	cout << x << " ";
//	Print(args...);
//}
//
////打印参数包内容 - 编译时递归处理
//template <class ...Args>
//void showList(Args&&... args)
//{
//	//cout << sizeof...(args) << endl;
//	Print(args...);
//	//记住,不能这样写,因为这个是运行时逻辑
//	//if (sizeof ...(args) == 0)
//		//return;
//}
//int main()
//{
//	showList();
//	showList(1);
//	showList(1, 'x');
//	showList(1, 'x', 3.14);
//	return 0;
//}

////打印参数包内容
//template <class ...Args>
//void showList(Args... args)
//{
//	//可变参数模板编译时解析
//	cout << sizeof...(args) << endl;
//	//C语言的可变参数用取数组元素的方式去取因为它是在允许时去取的,
//	//而这里是模板,类型都不确定,在编译时就要解析每个参数的类型
//	/*for (int i = 0; i < sizeof...(args); i++)
//	{
//		cout << args[i] << " ";
//	}
//	cout << endl;*/
//	//for循环依次解析是运行时逻辑,所以这个逻辑是走不通的
//	
//}
//int main()
//{
//	showList();
//	showList(1);
//	showList(1, 'x');
//	showList(1, 'x', 3.14);
//	return 0;
//}

////可变模板参数
////参数类型可变
////参数个数可变
//template <class ...Args>
//void showList(Args... args)
//{
//	cout << sizeof...(args) << endl;
//}
//
////固定参数个数的,类型不确定
////template <class T>
////void showList1(T&& x)
////{}
//
//int main()
//{
//	showList();
//	showList(1);
//	showList(1,'x');
//	showList(1,'x',3.14);
//	return 0;
//}


//Args是一个模板参数包,args是一个函数形参参数包
//声明一个参数包Args... args,这个参数包中可以包含0到任意个模板参数
//参数包代表多个类型和多个参数
//template <class ...Args>
//void showList(Args... args)
//{}
//template <class ...T>//(Args),并不是必须叫这个名称,但是一般都是这个名称
//void showList(T... args)
//{}
//template <class ...Args>
//void showList(Args&&... args)//这样写不是右值引用,在模板中这个叫做万能引用
//{}
//int main()
//{
//
//	return 0;
//}


//class Person
//{
//public:
//	Person(const char* name = "1111111111", int age = 0)
//		: _name(name)
//		, _age(age)
//	{}
//private:
//	Person(const Person& p);
//	Person& operator= (const Person& p);
//private:
//	wh::string _name;
//	int _age;
//};
//Person::Person(const Person& p) 
//{
//
//}
//Person& Person::operator=(const Person& p)
//{
//	return *this;
//}
//int main()
//{
//	Person s1;
//	Person s2 = s1;
//	Person s3 = std::move(s1);
//	Person s4;
//	s4 = std::move(s2);
//	return 0;
//}

//class Person
//{
//public:
//	Person(const char* name = "1111111111", int age = 0)
//		: _name(name)
//		, _age(age)
//	{}
//	//自动生成拷贝构造和移动构造,对_age完成值拷贝,对string调用它的拷贝构造
//	//移动构造对_age来说调用值拷贝,对string来说有移动构造调移动构造,没有移动
//	//构造调拷贝构造
//	Person(Person&& p) = default;//只写这个会报错,我们实现了移动构造,
//	//对其他函数也实现了一定的影响,如果只显示写了移动构造,但是又没写赋值,拷贝构造
//	//的话它是会报错的。
//	Person& operator= (Person&& p) = default;
//	Person (const Person& p) = default;
//	Person& operator= (const Person& p) = default;
//	~Person()
//	{}
//private:
//	wh::string _name;
//	int _age;
//};
//int main()
//{
//	Person s1;
//	Person s2 = s1;
//	Person s3 = std::move(s1);
//	Person s4;
//	s4 = std::move(s2);
//	return 0;
//}


//template <class _Ty>
//_Ty&& forward(remove_reference_t<_Ty>& _Arg) noexcept
//{ // forward an lvalue as either an lvalue or an rvalue
//	return static_cast<_Ty&&>(_Arg);
//} 
//void Fun(int& x) { cout << "左值引用" << endl; }
//void Fun(const int& x) { cout << "const 左值引用" << endl; }
//void Fun(int&& x) { cout << "右值引用" << endl; }
//void Fun(const int&& x) { cout << "const 右值引用" << endl; }
//在函数模板中
// && && -> && 引用折叠
// &  && -> & 往小了折,传
//传左值 -> 实例化成左值引用
//传右值 -> 实例化成右值引用
//传const左值 -> 实例化成const左值引用
//传const右值 -> 实例化成const右值引用
//template<class T>
//void Function(T&& t)
//{
//	//验证t是左值还是右值
//	//cout << typeid(t).name() << endl;
//	//typeid在看引用上面不行,所以我们把这个t向下传递,看看匹配
//	//Fun(t);
//	//其实这里向下传递一层也观察不出来,全部变成左值了,左值就正常传递
//	//如果是右值,右值引用本身的属性又变成左值了,move一下就全到右值去了
//	//还是不行
//	Fun(forward<T>(t));
//}
//void Function(int&& t)
//{
//	Fun(t);
//}
//void Function(int& t)
//{
//	Fun(t);
//}
//void Function(const int&& t)
//{
//	Fun(move(t));
//}
//void Function(const int& t)
//{
//	Fun(t);
//}
//int main()
//{
//	/*
//	int a = 10;
//	int& b = a;
//	cout << typeid(a).name() << endl;
//	cout << typeid(b).name() << endl;
//	//typeid不把引用类型打出来,它认为a是这块空间的名字,b也是这块空间
//	//的名字,只不过是别名而已,所以b的类型也是int,也说的过去
//	*/
//	
//	// 10是右值，推导出T为int，模板实例化为void Function(int&& t)
//	Function(10); // 右值
//	int a;
//	// a是左值，推导出T为int&，引用折叠，模板实例化为void Function(int& t)
//	Function(a); // 左值
//	// std::move(a)是右值，推导出T为int，模板实例化为void Function(int&& t)
//	Function(std::move(a)); // 右值
//	const int b = 8;
//	// a是左值，推导出T为const int&，引用折叠，模板实例化为void Function(const int&t)
//	Function(b); // const 左值
//	// std::move(b)右值，推导出T为const int，模板实例化为void Function(const int&&t)
//	Function(std::move(b)); // const 右值
//	
//	return 0;
//}


//namespace wh
//{
//	class string
//	{
//	public:
//		typedef char* iterator;
//		typedef const char* const_iterator;
//		iterator begin()
//		{
//			return _str;
//		}
//		iterator end()
//		{
//			return _str + _size;
//		}
//		const_iterator begin() const
//		{
//			return _str;
//		}
//		const_iterator end() const
//		{
//			return _str + _size;
//		}
//		string(const char* str = "")
//			:_size(strlen(str))
//			,_capacity(_size)
//		{
//			cout << "string(char* st)" << endl;
//			_str = new char[_capacity + 1];
//			strcpy(_str, str);
//
//		}
//		void swap(string& s)
//		{
//			::swap(_str, s._str);
//			::swap(_size, s._size);
//			::swap(_capacity, s._capacity);
//		}
//		//拷贝构造 - 左值
//		string(const string& s)
//			:_str(nullptr)
//		{
//			cout << "string(const string& s) -- 深拷贝" << endl;
//			reserve(s._capacity);
//			for (auto ch : s)
//			{
//				push_back(ch);
//			}
//		}
//		//赋值重载
//		string& operator=(const string& s)
//		{
//			cout << "string& operator=(string s) -- 深拷贝" << endl;
//			if (this != &s)
//			{
//				_str[0] = '\0';
//				_size = 0;
//				reserve(s._capacity);
//				for (auto ch : s)
//				{
//					push_back(ch);
//				}
//			}
//			return *this;
//		}
//		//移动构造 - 右值
//		//临时创建的对象,不能取地址,用完就要消亡了
//		string(string&& s)
//			:_str(nullptr)
//			,_size(0)
//			,_capacity(0)
//		{
//			cout << "string(string&& s) -- 移动拷贝" << endl;
//			swap(s);//直接抢夺资源
//		}
//		//移动赋值
//		string& operator=(string&& s)
//		{
//			cout << "operator=(string&& s) -- 移动拷贝" << endl;
//			swap(s);
//			return *this;
//		}
//		~string()
//		{
//			delete[] _str;
//			_str = nullptr;
//		}
//		char& operator[](size_t pos)
//		{
//			assert(pos < _size);
//			return _str[pos];
//		}
//		void reserve(size_t n)
//		{
//			if (n > _capacity)
//			{
//				char* tmp = new char[n + 1];
//				if (_str)
//				{
//					strcpy(tmp, _str);
//					delete[] _str;
//				}
//				_str = tmp;
//
//				_capacity = n;
//			}
//		}
//		void push_back(char ch)
//		{
//			if (_size >= _capacity)
//			{
//				size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
//				reserve(newcapacity);
//			}
//			_str[_size] = ch;
//			++_size;
//			_str[_size] = '\0';
//		}
//		string& operator+=(char ch)
//		{
//			push_back(ch);
//			return *this;
//		}
//		const char* c_str() const
//		{
//			return _str;
//		}
//	private:
//		char* _str = nullptr;
//		size_t _size = 0;
//		size_t _capacity = 0;
//	};
//	wh::string to_string(int value)
//	{
//		bool flag = true;
//		if (value < 0)
//		{
//			flag = false;
//			value = 0 - value;
//		}
//		wh::string str;
//		while (value > 0)
//		{
//			int x = value % 10;
//			value /= 10;
//			str += ('0' + x);
//		}
//		if (flag == false)
//		{
//			str += '-';
//		}
//		std::reverse(str.begin(), str.end());
//		//return move(str);
//		return str;
//	}
//} 
//
//void func(const wh::string& s)
//{
//	cout << "const wh::string& s" << endl;
//}
//void func(wh::string&& s)
//{
//	cout << "wh::string&& s" << endl;
//}
//int main()
//{
//	wh::string s1("11111111111111");
//	func(s1);//左值
//	func((wh::string&&)s1);
//	//强转一下,和move的效果一样,其实值还是那个值,
//	//到底识别成左值还是右值,编译器是可以随便变的,
//	//因为底层数据上并没有任何的差别,仅仅是识别的
//	//问题,
//	func(wh::string("22222222222"));//右值版本
//	func((wh::string&)wh::string("22222222222"));//左值版本
//	//右值其实是可以强转成左值的
//	//左值,右值这个属性是可以来回切的,因为这个属性是编译器
//	//在语法层的概念,数据层没有任何的区别,左值有空间,右值其实
//	//也有空间,只是编译器开辟的临时空间,在语法层没有对应的名字而已
//	//因为都是一些临时对象,匿名对象
//	return 0;
//}

//int main()
//{
//	hao::list<wh::string> lt;
//	wh::string s1 = "1111111111";
//	//move(s1);
//	lt.push_back(s1);
//	cout << "------------" << endl;
//	lt.push_back(wh::string("22222222222"));
//	cout << "------------" << endl;
//	lt.push_back("3333333333333333333");
//	cout << "------------" << endl;
//	lt.push_back(move(s1));//右值意外着资源可能会被转走
//	cout << "------------" << endl;
//	 
//	wh::string&& r1 = wh::string("4444444444444");
//
//	return 0;
//}
//在底层的角度,在结构和数据上左值和右值没有任何的区分,所以左值才能通过类型
//转换,其实就是改变上层的识别的问题,没有任何的标记,都是一块空间,只不过从语法
//层,被move了以后你的属性就是右值,调用的话就去调用移动构造,移动构造就会转移
//资源,


//引用的意义:减少拷贝
//左值引用解决的场景:引用传参/引用传返回值
//左值引用没有彻底解决的场景:传返回值

//这个场景比如使用传值返回,因为str是局部对象
//返回str的引用的话就是野引用。

//namespace wh
//{
//	class string
//	{
//	public:
//		typedef char* iterator;
//		typedef const char* const_iterator;
//		iterator begin()
//		{
//			return _str;
//		}
//		iterator end()
//		{
//			return _str + _size;
//		}
//		const_iterator begin() const
//		{
//			return _str;
//		}
//		const_iterator end() const
//		{
//			return _str + _size;
//		}
//		string(const char* str = "")
//			:_size(strlen(str))
//			,_capacity(_size)
//		{
//			cout << "string(char* st)" << endl;
//			_str = new char[_capacity + 1];
//			strcpy(_str, str);
//
//		}
//		void swap(string& s)
//		{
//			::swap(_str, s._str);
//			::swap(_size, s._size);
//			::swap(_capacity, s._capacity);
//		}
//		//拷贝构造 - 左值
//		string(const string& s)
//			:_str(nullptr)
//		{
//			cout << "string(const string& s) -- 深拷贝" << endl;
//			reserve(s._capacity);
//			for (auto ch : s)
//			{
//				push_back(ch);
//			}
//		}
//		//赋值重载
//		string& operator=(const string& s)
//		{
//			cout << "string& operator=(string s) -- 深拷贝" << endl;
//			if (this != &s)
//			{
//				_str[0] = '\0';
//				_size = 0;
//				reserve(s._capacity);
//				for (auto ch : s)
//				{
//					push_back(ch);
//				}
//			}
//			return *this;
//		}
//		//移动构造 - 右值
//		//临时创建的对象,不能取地址,用完就要消亡了
//		string(string&& s)
//			:_str(nullptr)
//			,_size(0)
//			,_capacity(0)
//		{
//			cout << "string(string&& s) -- 移动拷贝" << endl;
//			swap(s);//直接抢夺资源
//		}
//		//移动赋值
//		string& operator=(string&& s)
//		{
//			cout << "operator=(string&& s) -- 移动拷贝" << endl;
//			swap(s);
//			return *this;
//		}
//		~string()
//		{
//			delete[] _str;
//			_str = nullptr;
//		}
//		char& operator[](size_t pos)
//		{
//			assert(pos < _size);
//			return _str[pos];
//		}
//		void reserve(size_t n)
//		{
//			if (n > _capacity)
//			{
//				char* tmp = new char[n + 1];
//				if (_str)
//				{
//					strcpy(tmp, _str);
//					delete[] _str;
//				}
//				_str = tmp;
//
//				_capacity = n;
//			}
//		}
//		void push_back(char ch)
//		{
//			if (_size >= _capacity)
//			{
//				size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
//				reserve(newcapacity);
//			}
//			_str[_size] = ch;
//			++_size;
//			_str[_size] = '\0';
//		}
//		string& operator+=(char ch)
//		{
//			push_back(ch);
//			return *this;
//		}
//		const char* c_str() const
//		{
//			return _str;
//		}
//	private:
//		char* _str = nullptr;
//		size_t _size = 0;
//		size_t _capacity = 0;
//	};
//	wh::string to_string(int value)
//	{
//		bool flag = true;
//		if (value < 0)
//		{
//			flag = false;
//			value = 0 - value;
//		}
//		wh::string str;
//		while (value > 0)
//		{
//			int x = value % 10;
//			value /= 10;
//			str += ('0' + x);
//		}
//		if (flag == false)
//		{
//			str += '-';
//		}
//		std::reverse(str.begin(), str.end());
//		//return move(str);
//		return str;
//	}
//} 
//
//int main()
//{
//	wh::string  s1;
//	s1 = wh::to_string(1234);
//	return 0;
//}

//int main()
//{
//	//以下的p,b,c,*p都是左值
//	//左值:可以取地址
//	int* p = new int(0);
//	int b = 1;
//	const int c = b;
//	*p = 10;
//	string s("111111111");
//	s[0];
//
//	//右值引用给左值取别名:不能直接引用,但是move(左值)以后右值引用可以引用
//	int&& rrx1 = move(b);
//	int*&& rrx2 = move(p);
//	int&& rrx3 = move(*p);
//	string&& rrx4 = move(s);
//	//move原理
//	//底层没有左值引用和右值引用的概念,都是指针。
//	//move其实就是强制类型转换,底层实现确实复杂,但是本质就是强制转换
//	string&& rrx5 = (string&&)s;//这样写只是语法检查不能通过而已
//	return 0;
//}

//int main()
//{
//	int x = 0;
//	int& r1 = x;
//	int&& rr1 = x + 10;
//	return 0;
//}
//
////底层汇编代码
//int x = 0;
//0059182F  mov         dword ptr[x], 0 //把0给x变量
//int& r1 = x;
//00591836  lea         eax, [x] //取x变量的地址放到eax中 lea(取地址)
//00591839  mov         dword ptr[r1], eax //把eax的值move到r1中
////左值引用其实底层开空间了,开了一个r1的指针,底层就没有引用这个语法层概念
//int&& rr1 = x + 10;
//0059183C  mov         eax, dword ptr[x] //把x给eax
//0059183F  add         eax, 0Ah //eax中的值加上10
//00591842  mov         dword ptr[ebp - 30h], eax //开一段空间,把eax中的值放进去
//00591845  lea         ecx, [ebp - 30h] //取这块空间的地址放到ecx中
//00591848  mov         dword ptr[rr1], ecx //最后让rr1右值引用存ecx的地址
////从汇编层看,没有引用,只有指针,语法层面上我是你的别名,其实底层还是地址,还是要解引用。


//int main()
//{
//	//以下的p,b,c,*p都是左值
//	//左值:可以取地址
//	int* p = new int(0);
//	int b = 1;
//	const int c = b;
//	*p = 10;
//	string s("111111111");
//	s[0];
//
//	//左值引用给左值取别名
//	int& r1 = b;
//	int*& r2 = p;
//	int& r3 = *p;
//	string& r4 = s;
//
//	//右值:不能取地址
//	double x = 1.1, y = 2.2;
//	10;
//	x + y;//用临时对象存储加的结果
//	fmin(x , y);//临时对象存储返回值的结果
//	string("1111");
//	//右值引用给右值取别名
//	int&& rr1 = 10;
//	double&& rr2 = x + y;
//	double&& rr3 = fmin(x, y);
//
//	//------------------------------------------//
//	
//	//左值引用给右值取别名:不能直接引用,但是const左值引用可以
//	// 
//	//int& rx1 = 100;//常量,权限的放大
//	const int& rx1 = 100;
//	//int& rx2 = x + y;//临时对象具有常性
//	const int& rx2 = x + y;
//	//int& rx3 = fmin(x, y);//临时对象具有常性
//	const double& rx3 = fmin(x, y);
//	//string& rx4 = string("11111");//匿名对象具有常性
//	const string& rx4 = string("11111");
//
//
//	//如果只能push_back左值是非常麻烦的一件事情
//	vector<string> v;
//	string s1("111");
//	v.push_back(s1);
//	//所以可以push_back右值对象
//	v.push_back(string("111"));
//	//还可以push_back字符串,因为单参数构造支持隐式类型转换
//	v.push_back("111");
//
//	//------------------------------------------//
//
//	//右值引用给左值取别名:不能直接引用,但是move(左值)以后右值引用可以引用
//	int&& rrx1 = move(b);
//	int*&& rrx2 = move(p);
//	int&& rrx3 = move(*p);
//	string&& rrx4 = move(s);
//	return 0;
//}


//int main()
//{
//	//右值:不能取地址
//	double x = 1.1, y = 2.2;
//	//以下几个都是常见的右值,常量临时对象,匿名对象
//	10;
//	x + y;//用临时对象存储加的结果
//	fmin(x , y);//临时对象存储返回值的结果
//	string("1111");
//	//cout << &10 << endl;
//	//cout << &(x + y) << endl;
//	//cout << &(fmin(x, y)) << endl;
//	//cout << &string("1111") << endl;
//	//右值一般是常量和临时对象,匿名对象
//	return 0;
//}

//int main()
//{
//	//以下的p,b,c,*p都是左值
//	//左值:可以取地址
//	int* p = new int(0);
//	int b = 1;
//	const int c = b;//这里的b(左值)在右边
//	*p = 10;
//	string s("111111111");
//	s[0];
//	//左值不一定在左边,也可以在右边
//	return 0;
//}

//int main()
//{
//	//静态数组越界的检查
//	int a[10] = { 0 };
//	//越界读 - 检查不出来
//	cout << a[10] << endl;
//	cout << a[11] << endl;
//	//越界写 - 前面会报错,后面不一定
//	//a[10] = 1;//报错
//	a[15] = 1;//未报错
//
//	//越界的检查很严格
//	array<int, 10> arr;
//	cout << arr[10] << endl;
//	//定义大数组的话栈有可能会溢出,有风险
//
//	//其实我们用vector也挺爽的
//	vector<int> v(10,0);
//	return 0;
//}


//int main()
//{
//	vector<int> v = { 1,2,3,4,5,6,7,8,9,10 };
//	for (const auto& e : v)
//	{
//		cout << e << " ";
//	}
//	cout << endl;
//	return 0;
//}


//void func(int x)
//{
//	cout << "void func(int x)" << endl;
//}
//void func(int* p)
//{
//	cout << "void func(int* p)" << endl;
//}
//int main()
//{
//	//C++中的NULL
//	func(NULL);
//
//	//C中替换之后的NULL
//	//func((void*)0);
//	//会报错,因为这是void*,而函数中是int*和int,两个都不匹配,C++中
//	//要需要强转的,而C语言不需要强转。
//
//	//这个代码在C++中是不可以的,在C语言中是可以的。
//	/*void* p1 = 0;
//	int* p2 = p1;*/
//
//	//C++中的nullptr
//	func(nullptr);
//	return 0;
//}

//struct Point
//{
//	int _x;
//	int _y;
//};
//class Date
//{
//	public :
//	Date(int year = 1, int month = 1, int day = 1)
//		: _year(year)
//		, _month(month)
//		, _day(day)
//	{
//		cout << "Date(int year, int month, int day)" << endl;
//	} 
//	Date(const Date& d)
//		: _year(d._year)
//		, _month(d._month)
//		, _day(d._day)
//	{
//		cout << "Date(const Date& d)" << endl;
//	}
//private:
//	int _year;
//	int _month;
//	int _day;
//};
//
////decltype的一些使用场景
//template<class T1,class T2>
//void F(T1 t1, T2 t2)
//{
//	decltype(t1 * t2) ret;
//	cout << typeid(ret).name() << endl;
//}
//int main()
//{
//	const int x = 1;
//	double y = 2.2;
//	decltype(x * y) ret;//ret的类型是double;
//	decltype(&x) p;//p的类型是int*;
//	cout << typeid(ret).name() << endl;
//	cout << typeid(p).name() << endl;
//	F(1, 'a');
//
//	map<string, string> dict = { {"soft","排序"},{"insert","插入"} };
//	map<string, string>::iterator it = dict.begin();
//	vector<decltype(it)> v;
//	return 0;
//}
//typeid只能拿到类型的字符串,只能打印,除了只能打印出来看一看,不能做任何
//事情,不能用typeid.name来声明,仅仅只能做到把对应的类型转换成字符串。
//decltype推导出来的类型可用定义对象,也可以用来传导模板参数等等。


//int main()
//{
//	int i = 10;
//	auto p = &i;
//	auto pf = strcpy;
//	cout << typeid(p).name() << endl;
//	cout << typeid(pf).name() << endl;
//	map<string, string> dict = { {"soft","排序"},{"insert","插入"} };
//	//map<string, string>::iterator it = dict.begin();
//	auto it = dict.begin();
//	return 0;
//}

//int main()
//{
//	std::initializer_list<int> mylist;
//	mylist = { 10,20,30 };
//	
//	return 0;
//}


// 一切皆可用列表初始化，且可以不加=
//int main()
//{
//	// C++98支持的
//	int a1[] = { 1, 2, 3, 4, 5 };
//	int a2[5] = { 0 };
//	Point p = { 1, 2 };
//	// C++11支持的
//	// 内置类型支持
//	int x1 = { 2 };
//	// 自定义类型支持
//	// 这里本质是用{ 2025, 1, 1}构造⼀个Date临时对象
//	// 临时对象再去拷贝构造d1，编译器优化后合二为一变成{ 2025, 1, 1}直接构造初始化d1
//	// 运行一下，我们可以验证上面的理论，发现是没调用拷贝构造的
//	Date d1 = { 2025, 1, 1 };
//	// 这里d2引用的是{ 2024, 7, 25 }构造的临时对象
//	const Date& d2 = { 2024, 7, 25 };
//	// 需要注意的是C++98支持单参数时类型转换，也可以不用{}
//	Date d3 = { 2025 };
//	Date d4 = 2025;
//	// 可以省略掉=
//	Point p1{ 1, 2 };
//	int x2{ 2 };
//	Date d6{ 2024, 7, 25 };
//	const Date& d7{ 2024, 7, 25 };
//	// 不支持，只有{}初始化，才能省略=
//	// Date d8 2025;
//	vector<Date> v;
//	v.push_back(d1);
//	v.push_back(Date(2025, 1, 1));
//	// 比起有名对象和匿名对象传参，这⾥{}更有性价⽐
//	v.push_back({ 2025, 1, 1 });
//	return 0;
//}